package cn.core.coding.rest;

import cn.core.coding.ao.ProConfAO;
import cn.core.coding.eo.DbTableConf;
import cn.core.coding.eo.ProjectModule;
import cn.core.coding.qo.DbTableConfQO;
import cn.core.coding.qo.ProjectModuleQO;
import cn.core.coding.service.CodingService;
import cn.core.coding.service.DbTableConfService;
import cn.core.coding.service.ProjectModuleService;
import cn.core.coding.vo.DbTableConfAndInfoVO;
import cn.core.coding.vo.DbTablesInfoVO;
import cn.core.tool.exception.CoreException;
import cn.core.tool.rest.CoreController;
import cn.core.tool.util.CoreTool;
import cn.core.tool.util.CoreTree;
import cn.core.tool.util.Param;
import cn.core.tool.util.Res;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 生成代码 REST API
 */
@Log4j2
@RestController
@Scope("prototype")
@RequestMapping("coding/coding")
public class CodingController extends CoreController {

  @Resource
  private CodingService codingService;

  @Resource
  private ProjectModuleService projectModuleService;

  @Resource
  private DbTableConfService dbTableConfService;

  /**
   * 动态添加当前账号对应项目模块的数据源
   * @param param 参数
   * @return 返回
   */
  @PostMapping("addDataSource")
  public Res<ProjectModule> addDataSource(@RequestBody Param<ProjectModule> param) throws Exception {
    Res<ProjectModule> res = new Res<>("数据源加载成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      codingService.addDataSource(param.get().getId());
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 获取数据库所有表信息
   * @param param 参数
   * @return 返回
   */
  @PostMapping("getDbAllTablesInfo")
  public Res<DbTablesInfoVO> getDbAllTablesInfo(@RequestBody Param<ProjectModule> param) throws Exception {
    Res<DbTablesInfoVO> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(codingService.getDbAllTablesInfo(param.get().getId()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 数据库表配置 >>> 批量保存或修改
   * @param param 参数
   * @return 返回
   */
  @PostMapping("batchSaveOrUpdateDbTablesConf")
  public Res<DbTableConf> batchSaveOrUpdateDbTablesConf(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("数据库表配置信息保存成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(codingService.batchSaveOrUpdateDbTableConf(param.getData()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 获取项目模块数据库表配置树
   * @param param 参数
   * @return 返回
   */
  @PostMapping("getProjectModuleDbTableConfTreeData")
  public Res<CoreTree<?>> getProjectModuleDbTableConfTreeData(@RequestBody Param<ProjectModule> param) throws Exception {
    Res<CoreTree<?>> res = new Res<>();
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      res.setData(codingService.getProjectModuleDbTableConfTreeData(param.get().getId()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 生成项目模块
   * @param param 参数
   * @return 返回
   */
  @PostMapping("generateProjectModule")
  public Res<ProjectModule> generateProjectModule(@RequestBody Param<ProjectModule> param) throws Exception {
    Res<ProjectModule> res = new Res<>("后台项目模块生成成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get()) || CoreTool.isNullStr(param.get().getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(param.get().getId()));
      ProConfAO proConfParam = new ProConfAO()
          .setCodeCi(projectModule.getCodeCi())
          .setProjectPath(projectModule.getProjectPath())
          .setProjectModuleName(projectModule.getProjectModuleName())
          .setProjectModuleNotes(projectModule.getProjectModuleNotes());
      codingService.generateProjectModule(codingService.getProjectModuleConf(proConfParam));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 生成代码 >>> pro
   * @param param 参数
   * @return 返回
   */
  @PostMapping("generate")
  public Res<DbTableConf> generate(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("java 后台代码生成成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (DbTableConf eo : param.getData()) {
        DbTableConf dbTableConf = dbTableConfService.pk(new DbTableConfQO().setId(eo.getId()));
        if (CoreTool.isNotNullEo(dbTableConf)) {
          ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(dbTableConf.getFkid()));
          DbTableConfAndInfoVO dbTableConfAndInfoVO = codingService.getDbTableConfAndInfo(codingService.toProConfAndDbTableConfParam(projectModule, dbTableConf));
          codingService.generateEntityFile(dbTableConfAndInfoVO);
          codingService.generateQueryFile(dbTableConfAndInfoVO);
          codingService.generateVoFile(dbTableConfAndInfoVO);
          codingService.generateMapperPersistentInterfacesFile(dbTableConfAndInfoVO);
          codingService.generateMapperSqlFile(dbTableConfAndInfoVO);
//          codingService.generateServiceInterfacesFile(dbTableConfAndInfoVO);
//          codingService.generateServiceImplementFile(dbTableConfAndInfoVO);
          codingService.generateServiceFile(dbTableConfAndInfoVO);
          codingService.generateRestFile(dbTableConfAndInfoVO);
        }
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 删除代码文件 >>> pro
   * @param param 参数
   * @return 返回
   */
  @PostMapping("delProCodeFiles")
  public Res<DbTableConf> delProCodeFiles(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("java 后台代码删除成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (DbTableConf eo : param.getData()) {
        DbTableConf dbTableConf = dbTableConfService.pk(new DbTableConfQO().setId(eo.getId()));
        if (CoreTool.isNotNullEo(dbTableConf)) {
          ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(dbTableConf.getFkid()));
          codingService.delProCodeFiles(codingService.getDbTableConfAndInfo(codingService.toProConfAndDbTableConfParam(projectModule, dbTableConf)));
        }
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 重新生成代码 >>> pro
   * @param param 参数
   * @return 返回
   */
  @PostMapping("regenerate")
  public Res<DbTableConf> regenerate(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("java 后台代码重新生成成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (DbTableConf eo : param.getData()) {
        DbTableConf dbTableConf = dbTableConfService.pk(new DbTableConfQO().setId(eo.getId()));
        if (CoreTool.isNotNullEo(dbTableConf)) {
          ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(dbTableConf.getFkid()));
          DbTableConfAndInfoVO dbTableConfAndInfoVO = codingService.getDbTableConfAndInfo(codingService.toProConfAndDbTableConfParam(projectModule, dbTableConf));
          codingService.generateEntityFile(dbTableConfAndInfoVO);
          codingService.regenerateQueryFile(dbTableConfAndInfoVO);
          codingService.regenerateVoFile(dbTableConfAndInfoVO);
          codingService.regenerateMapperSqlFile(dbTableConfAndInfoVO);
        }
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 生成代码 >>> vue
   * @param param 参数
   * @return 返回
   */
  @PostMapping("generateVue")
  public Res<DbTableConf> generateVue(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("vue3 前端代码生成成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (DbTableConf eo : param.getData()) {
        DbTableConf dbTableConf = dbTableConfService.pk(new DbTableConfQO().setId(eo.getId()));
        if (CoreTool.isNotNullEo(dbTableConf)) {
          ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(dbTableConf.getFkid()));
          DbTableConfAndInfoVO dbTableConfAndInfoVO = codingService.getDbTableConfAndInfo(codingService.toProConfAndDbTableConfParam(projectModule, dbTableConf));
          codingService.generateVueEntityFile(dbTableConfAndInfoVO);
          codingService.generateVueQueryFile(dbTableConfAndInfoVO);
          codingService.generateVueVoFile(dbTableConfAndInfoVO);
          codingService.generateVueApiServiceFile(dbTableConfAndInfoVO);
          codingService.generateVueStoreFile(dbTableConfAndInfoVO);
          codingService.generateVueViewFile(dbTableConfAndInfoVO);
        }
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 删除代码文件 >>> vue
   * @param param 参数
   * @return 返回
   */
  @PostMapping("delVueCodeFiles")
  public Res<DbTableConf> delVueCodeFiles(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("vue3 前端代码删除成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (DbTableConf eo : param.getData()) {
        DbTableConf dbTableConf = dbTableConfService.pk(new DbTableConfQO().setId(eo.getId()));
        if (CoreTool.isNotNullEo(dbTableConf)) {
          ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(dbTableConf.getFkid()));
          codingService.delVueCodeFiles(codingService.getDbTableConfAndInfo(codingService.toProConfAndDbTableConfParam(projectModule, dbTableConf)));
        }
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

  /**
   * 重新生成代码 >>> vue
   * @param param 参数
   * @return 返回
   */
  @PostMapping("regenerateVue")
  public Res<DbTableConf> regenerateVue(@RequestBody Param<DbTableConf> param) throws Exception {
    Res<DbTableConf> res = new Res<>("vue3 前端代码重新生成成功！");
    try {
      if (CoreTool.isNullEo(param) || CoreTool.isEmpty(param.getData())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (DbTableConf eo : param.getData()) {
        DbTableConf dbTableConf = dbTableConfService.pk(new DbTableConfQO().setId(eo.getId()));
        if (CoreTool.isNotNullEo(dbTableConf)) {
          ProjectModule projectModule = projectModuleService.pk(new ProjectModuleQO().setId(dbTableConf.getFkid()));
          DbTableConfAndInfoVO dbTableConfAndInfoVO = codingService.getDbTableConfAndInfo(codingService.toProConfAndDbTableConfParam(projectModule, dbTableConf));
          codingService.generateVueEntityFile(dbTableConfAndInfoVO);
          codingService.regenerateVueQueryFile(dbTableConfAndInfoVO);
          codingService.regenerateVueVoFile(dbTableConfAndInfoVO);
          codingService.generateVueViewFile(dbTableConfAndInfoVO);
        }
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
    return res;
  }

}
